#include "uart.h"
#include "exception.h"
#include "systick.h"
#include "led.h"
#include "task.h"

void SysTickInit(void)
{
	SysTick_Type *SysTick = (SysTick_Type *)SysTick_BASE;
	/* 1. set period : 1S  */
	/* 2. set Load */
	SysTick->VAL  = SYSTICK_FRE;
	SysTick->LOAD = SYSTICK_FRE;
	
	/* 3. select clk source, enable systick, enable exception 
	 *  BIT[2] : clk source, process clk
	 *  BIT[1] : enable exception
	 *  BIT[0] : enable systick
	 */
	SysTick->CTRL = (1<<2) | (1<<1) | (1<<0);
}

// systick.c 中修改任务切换逻辑
void SysTick_Handler(int lr_bak, int old_sp)
{
    int stack;
    int pre_task;
    int new_task;
    
    SCB_Type * SCB = (SCB_Type *)SCB_BASE_ADDR;
        
    /* 清除异常状态 */
    SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk;

    /* 如果还没有创建好任务, 直接返回 */
    if (!is_task_running())
    {
        return;
    }
    
    /* 启动第1个任务或者切换任务 */
    if (cur_task == -1)
    {
        /* 从就绪队列获取第一个任务 */
        new_task = scheduler();
        if (new_task == -1) return;
        
        cur_task = new_task;
        stack = get_stack(cur_task);
        StartTask_asm(stack, lr_bak);
        return;
    }
    else
    {
        /* 切换任务：保存当前任务到就绪队列 */
        pre_task = cur_task;
        task_add_to_ready(&tasks[pre_task]);  // 将当前任务重新加入就绪队列
        
        /* 获取下一个任务 */
        new_task = scheduler();
        if (new_task == -1 || pre_task == new_task)
            return;
        
        /* 保存当前任务栈指针 */
        set_task_stack(pre_task, old_sp);
        
        /* 切换到新任务 */
        stack = get_stack(new_task);
        cur_task = new_task;
        StartTask_asm(stack, lr_bak);
    }
}
